package org.zjvis.datascience.web.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.zjvis.datascience.common.dto.ProjectDTO;
import org.zjvis.datascience.common.model.ApiResult;
import org.zjvis.datascience.common.model.ApiResultCode;
import org.zjvis.datascience.common.dto.ModelLocalDTO;
import org.zjvis.datascience.common.util.JwtUtil;
import org.zjvis.datascience.common.util.ModelUtil;
import org.zjvis.datascience.common.util.RestTemplateUtil;
import org.zjvis.datascience.common.vo.ModelLocalVO;
import org.zjvis.datascience.service.ModelLocalService;
import org.zjvis.datascience.service.ProjectService;

@RequestMapping("/modelLocal")
@RestController
@Api(tags = "modelLocal", description = "本地模型接口")
@Validated
public class ModelLocalController {

    private final static Logger logger = LoggerFactory.getLogger("ModelLocalController");

    @Autowired
    private ModelLocalService modelLocalService;

    @Autowired
    private RestTemplateUtil restTemplateUtil;

    @PostMapping(value = "/loadPanel")
    @ResponseBody
    @ApiOperation(value = "加载panel", notes = "加载panel")
    public ApiResult<JSONObject> loadPanel(HttpServletRequest request, @RequestBody JSONObject params) {
        params.put("userId", JwtUtil.getCurrentUserId());
        JSONObject panels = modelLocalService.loadPanel(params);
        return ApiResult.valueOf(panels);
    }

    @PostMapping(value = "/loadModel")
    @ResponseBody
    @ApiOperation(value = "加载模型", notes = "加载模型")
    public ApiResult<Void> loadModel(HttpServletRequest request, @RequestBody JSONObject params) {
        if (StringUtils.isEmpty(params.getString("projectId")) || StringUtils
            .isEmpty(params.getString("modelId"))) {
            return ApiResult.valueOf(ApiResultCode.PARAM_ERROR);
        }
        Long userId = JwtUtil.getCurrentUserId();
        modelLocalService.loadModel(userId, params.getLong("projectId"), params.getLong("folderId"),
            params.getJSONArray("modelId"));
        return ApiResult.valueOf(ApiResultCode.SUCCESS);
    }

    @PostMapping(value = "/create")
    @ResponseBody
    @ApiOperation(value = "添加模型", notes = "添加新建模型")
    public ApiResult<Long> create(HttpServletRequest request, @RequestBody ModelLocalVO vo) {
        if (StringUtils.isEmpty(vo.getName())) {
            return ApiResult.valueOf(ApiResultCode.PARAM_ERROR);
        }
        if (!CollectionUtils.isEmpty(modelLocalService.queryByName(vo.getName()))) {
            return ApiResult.valueOf(ApiResultCode.MODEL_NAME_DUP);
        }
        Long id = modelLocalService.create(vo.toModelLocal());

        return ApiResult.valueOf(id);
    }

    @PostMapping(value = "/update")
    @ResponseBody
    @ApiOperation(value = "更新模型", notes = "更新模型信息")
    public ApiResult<Void> update(HttpServletRequest request, @RequestBody ModelLocalVO vo) {
        if (vo.getId() == null) {
            return ApiResult.valueOf(ApiResultCode.PARAM_ERROR);
        }
        modelLocalService.update(vo.toModelLocal());

        return ApiResult.valueOf(ApiResultCode.SUCCESS);
    }

    @PostMapping(value = "/updateAll")
    @ResponseBody
    @ApiOperation(value = "更新所有本地模型信息", notes = "更新所有本地模型信息")
    public ApiResult<Void> updateAll(HttpServletRequest request, @RequestBody JSONObject params) {
        modelLocalService.updateAll();

        return ApiResult.valueOf(ApiResultCode.SUCCESS);
    }

    @PostMapping(value = "/delete")
    @ResponseBody
    @ApiOperation(value = "删除模型", notes = "删除模型文件及模型信息")
    public ApiResult<Void> delete(HttpServletRequest request, @RequestBody JSONObject params) {
        if (StringUtils.isEmpty(params.getString("id"))) {
            return ApiResult.valueOf(ApiResultCode.PARAM_ERROR);
        }
        modelLocalService.delete(params.getLong("id"));

        return ApiResult.valueOf(ApiResultCode.SUCCESS);
    }

    @PostMapping(value = "/deleteFromProject")
    @ResponseBody
    @ApiOperation(value = "删除模型", notes = "删除模型文件及模型信息")
    public ApiResult<Void> deleteFromProject(HttpServletRequest request, @RequestBody JSONObject params) {
        if (StringUtils.isEmpty(params.getString("id")) || StringUtils.isEmpty(params.getString("pipelineId"))) {
            return ApiResult.valueOf(ApiResultCode.PARAM_ERROR);
        }
        Long pipelineId = params.getLong("pipelineId");
        Long id = params.getLong("id");
        Long authRes = modelLocalService.modelDelAuth(id, pipelineId, false);
        if (authRes != 0L) {
            return ApiResult.valueOf(ApiResultCode.MODEL_IN_USE);
        }
        modelLocalService.deleteFromProject(params.getLong("id"));

        return ApiResult.valueOf(ApiResultCode.SUCCESS);
    }

    @PostMapping(value = "/query")
    @ResponseBody
    @ApiOperation(value = "搜索模型", notes = "搜索模型，支持模糊搜索")
    public ApiResult<JSONObject> query(HttpServletRequest request,
        @RequestBody JSONObject params) {
        if (StringUtils.isEmpty(params.getString("pageIndex")) || StringUtils
            .isEmpty(params.getString("pageSize"))) {
            return ApiResult.valueOf(ApiResultCode.PARAM_ERROR);
        }
        params.put("userId", JwtUtil.getCurrentUserId());
        JSONObject ret = modelLocalService.query(params);

        return ApiResult.valueOf(ret);
    }

    @PostMapping(value = "/queryById")
    @ResponseBody
    @ApiOperation(value = "根据id搜索模型", notes = "根据id搜索模型")
    public ApiResult<ModelLocalDTO> queryById(HttpServletRequest request,
        @RequestBody ModelLocalVO vo) {
        if (vo.getId() == null) {
            return ApiResult.valueOf(ApiResultCode.PARAM_ERROR);
        }
        ModelLocalDTO model = modelLocalService.queryById(vo.getId());

        return ApiResult.valueOf(model);
    }

    @PostMapping(value = "/queryProjectIds")
    @ResponseBody
    @ApiOperation(value = "根据模型id搜索已加载的项目", notes = "根据模型id搜索已加载的项目")
    public ApiResult<List<ProjectDTO>> queryProjectIds(HttpServletRequest request,
        @RequestBody JSONObject params) {
        if (StringUtils.isEmpty(params.getString("modelId"))) {
            return ApiResult.valueOf(ApiResultCode.PARAM_ERROR);
        }
        params.put("userId", JwtUtil.getCurrentUserId());
        List<ProjectDTO> projects = modelLocalService.queryProjectIds(params);

        return ApiResult.valueOf(projects);
    }

    @PostMapping(value = "/queryByUid")
    @ResponseBody
    @ApiOperation(value = "查询模型版本", notes = "查询模型版本")
    public ApiResult<List<ModelLocalDTO>> queryByUid(HttpServletRequest request,
        @RequestBody JSONObject params) {
        if (StringUtils.isEmpty(params.getString("uid"))) {
            return ApiResult.valueOf(ApiResultCode.PARAM_ERROR);
        }
        params.put("userId", JwtUtil.getCurrentUserId());
        List<ModelLocalDTO> modelDTOS = modelLocalService.queryByUid(params);

        return ApiResult.valueOf(modelDTOS);
    }

    @PostMapping(value = "/extractKeywords")
    @ResponseBody
    @ApiOperation(value = "提取关键词", notes = "提取关键词")
    public ApiResult<JSONArray> extractKeywords(HttpServletRequest request,
        @RequestBody JSONObject params)
        throws IOException {
        if (StringUtils.isEmpty(params.getString("sentence"))) {
            return ApiResult.valueOf(ApiResultCode.PARAM_ERROR);
        }
        params.put("apiPath", "extract_keywords");
        String ret = restTemplateUtil.submitFlaskJob(params);
        JSONArray keywords = JSONArray.parseArray(ret);

        return ApiResult.valueOf(keywords);
    }

}